#include "txr_algo_dlm_rec.h"
#include <boost/filesystem.hpp>
#include <QSysInfo>
#include <QDebug>
#include <QCoreApplication>
#include <QDir>

#include <iostream>
#include "../tk_utility/tk_mutex.h"
#include "txr_algo_dlm_rec_impl.h"

using namespace tk;
static TkMutex g_dlm_mutex;

namespace txr_algo_dlm_rec
{
	typedef TxrAlgoDlmRecImpl* (*FuncCreateDlmRecObj)();
	typedef void(*FuncDeleteDlmRecObj)(TxrAlgoDlmRecImpl*);
	
	TxrAlgoDlmRec::TxrAlgoDlmRec()
	{
	}
	TxrAlgoDlmRec::~TxrAlgoDlmRec()
	{
		Release();
	}

	tk_bool TxrAlgoDlmRec::Load(st_dlm_cfg & cfg)
	{
		TkMutexLocker lock(g_dlm_mutex);

		QString app_path = QCoreApplication::applicationDirPath();
		switch (GetDlmType(cfg))
		{
		// Load V1 version of recognition library
		case DLM_REC_TYPE_V1:
			m_lib_dlm = new QLibrary(QDir::toNativeSeparators(app_path + "/txr_algo_dlm_rec_v1"));
			std::cout << "Load V1 version of recognition library" << std::endl;
			break;
		// Load V1 optimized version of recognition library 
		case DLM_REC_TYPE_V1_O:
			m_lib_dlm = new QLibrary(QDir::toNativeSeparators(app_path + "/txr_algo_dlm_rec_v1_o"));
			std::cout << "Load V1 optimized version of recognition library" << std::endl;
			break;	
		default:
			return TK_FALSE;
		}

		if (m_lib_dlm)
		{
			if (!m_lib_dlm->load())
			{
				qWarning() << "Library load fail: " << m_lib_dlm->errorString();
				return TK_FALSE;
			}
			FuncCreateDlmRecObj func = (FuncCreateDlmRecObj)(m_lib_dlm->resolve("CreateDlmRecObj"));
			if (func)
			{
				m_dlm_obj = func();
				if (m_dlm_obj)
				{
					return m_dlm_obj->Load(cfg);
				}
			}
		}
		return TK_FALSE;
	}

	void TxrAlgoDlmRec::Release()
	{
		TkMutexLocker lock(g_dlm_mutex);
		if (m_lib_dlm)
		{
			FuncDeleteDlmRecObj func = (FuncDeleteDlmRecObj)(m_lib_dlm->resolve("DeleteDlmRecObj"));
			if (func)
			{
				func(m_dlm_obj);
				m_dlm_obj = TK_NULL_PTR;
			}
			m_lib_dlm->unload();
			m_lib_dlm = TK_NULL_PTR;
		}
	}

	void TxrAlgoDlmRec::Detect(st_detect_unit * p_unit, tk_int32 size)
	{
		TkMutexLocker lock(g_dlm_mutex);
		if (m_dlm_obj)
		{
			m_dlm_obj->Detect(p_unit, size);
		}
	}
	tk_bool TxrAlgoDlmRec::IsVaild()
	{
		return m_dlm_obj != TK_NULL_PTR;
	}

	tk_int32 TxrAlgoDlmRec::BatchSize()
	{
		TkMutexLocker lock(g_dlm_mutex);
		if (m_dlm_obj)
		{
			return m_dlm_obj->BatchSize();
		}
		return 0;
	}
	//=============================================================================
	/**
	 * 获取DLM模型类型
	 * 该函数在Load()函数中被调用,用于在加载模型时确定模型的具体类型
	 * 首先检查配置中是否已指定类型,如果已指定则直接返回
	 * 否则通过检查权重文件后缀来判断是V1还是V1_O版本
	 */
	DLM_TYPE TxrAlgoDlmRec::GetDlmType(st_dlm_cfg & cfg)
	{
		if (cfg.type != DLM_REC_TYPE_UNKNOWN)
		{
			return cfg.type;
		}
		using namespace boost::filesystem;
		{
			// 检查V1版本模型文件
			if (exists(path(std::string(cfg.file_path_name) + SUFFIX_V1)))
			{
				return DLM_REC_TYPE_V1;
			}
			// 检查V2版本模型文件
			else if (exists(path(std::string(cfg.file_path_name) + SUFFIX_V1_O)))
			{
				return DLM_REC_TYPE_V1_O;
			}
			
		}
		return DLM_REC_TYPE_UNKNOWN;
	}
}//namespace txr_algo_dlm_cls
